home *** CD-ROM | disk | FTP | other *** search
/ Aminet 2 / Aminet AMIGA CDROM (1994)(Walnut Creek)[Feb 1994][W.O. 44790-1].iso / Aminet / comm / misc / xprz31.lha / XprZmodem / Zm.c < prev    next >
C/C++ Source or Header  |  1993-08-13  |  20KB  |  873 lines

  1. /**********************************************************************
  2.  *   Z M . C
  3.  *    ZMODEM protocol primitives
  4.  *    01-19-87  Chuck Forsberg Omen Technology Inc
  5.  *
  6.  * 29 July 89:
  7.  * Major overhaul by Rick Huebner for adaptation to Amiga XPR protocol spec
  8.  *
  9.  * 28 October 89:
  10.  * Converted to Lattice C 5.04
  11.  *
  12.  * 15 November 1991
  13.  * Code added to support CRC-32 by William M. Perkins.
  14.  *
  15.  * Version 2.63, 30 July 1993 build in locale, by Rainer Hess
  16.  **********************************************************************/
  17.  
  18. #include "xprzmodem_all.h"
  19. #include "Zcrc.h"
  20.  
  21. #define CATCOMP_NUMBERS
  22. #include "xprzmodem_catalog.h"
  23.  
  24. static char *frametypes[] =
  25. {
  26.   "Carrier Lost",        /* -3 */
  27.   "TIMEOUT",            /* -2 */
  28.   "ERROR",            /* -1 */
  29. #define FTOFFSET 3
  30.   "ZRQINIT",
  31.   "ZRINIT",
  32.   "ZSINIT",
  33.   "ZACK",
  34.   "ZFILE",
  35.   "ZSKIP",
  36.   "ZNAK",
  37.   "ZABORT",
  38.   "ZFIN",
  39.   "ZRPOS",
  40.   "ZDATA",
  41.   "ZEOF",
  42.   "ZFERR",
  43.   "ZCRC",
  44.   "ZCHALLENGE",
  45.   "ZCOMPL",
  46.   "ZCAN",
  47.   "ZFREECNT",
  48.   "ZCOMMAND",
  49.   "ZSTDERR",
  50.   "xxxxx"
  51. #define FRTYPES 22        /* Total number of frame types in this array */
  52.         /*  not including psuedo negative entries */
  53. };
  54.  
  55. static UBYTE DLE_actions[] =
  56. {
  57.   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
  58.   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  59.   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  60.   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  61.  
  62.   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  63.   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  64.   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  65.   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  66. };
  67.  
  68. /**********************************************************
  69.  *      void zsbhdr(struct Vars *v, USHORT type)
  70.  *
  71.  * Send ZMODEM binary header hdr of type type
  72.  **********************************************************/
  73. void
  74. zsbhdr (struct Vars *v, USHORT type)
  75. {
  76.   UBYTE *hdr = v->Txhdr;
  77.   short n;
  78.   USHORT crc;
  79.   ULONG crc32;
  80.  
  81. #ifdef DEBUGLOG
  82.   D (DEBUGINFO);
  83. #endif
  84.  
  85.   xsendline (v, ZPAD);
  86.   xsendline (v, ZDLE);
  87.  
  88.   if (v->Crc32t = v->Txfcs32)    /* zsbh32() */
  89.     {
  90.       xsendline (v, ZBIN32);
  91.       zsendline (v, (UBYTE) type);
  92.  
  93. #ifdef DEBUGLOG
  94.       xprsprintf (v->Msgbuf, "zsbh32: %s %lx\n", frametypes[type + FTOFFSET],
  95.           v->Txpos);
  96.       dlog (v, v->Msgbuf);
  97.       D (DEBUGINFO);
  98. #endif
  99.       crc32 = 0xFFFFFFFFL;
  100.       crc32 = UPDC32 (type, crc32);
  101.  
  102.       for (n = 4; --n >= 0; ++hdr)
  103.     {
  104.       crc32 = UPDC32 ((0377 & *hdr), crc32);
  105.       zsendline (v, *hdr);
  106.     }
  107.       crc32 = ~crc32;
  108.       for (n = 4; --n >= 0;)
  109.     {
  110.       zsendline (v, (int) crc32);
  111.       crc32 >>= 8;
  112.     }
  113.     }
  114.   else
  115.     {
  116.       xsendline (v, ZBIN);
  117.       zsendline (v, (UBYTE) type);
  118.  
  119. #ifdef DEBUGLOG
  120.       xprsprintf (v->Msgbuf, "zsbhdr: %s %lx\n", frametypes[type + FTOFFSET],
  121.           v->Txpos);
  122.       dlog (v, v->Msgbuf);
  123.       D (DEBUGINFO);
  124. #endif
  125.       crc = updcrc (type, 0);
  126.       for (n = 4; --n >= 0;)
  127.     {
  128.       zsendline (v, *hdr);
  129.       crc = updcrc (((USHORT) (*hdr++)), crc);
  130.     }
  131.  
  132.       crc = updcrc (((USHORT) 0), crc);
  133.       crc = updcrc (((USHORT) 0), crc);
  134.       zsendline (v, (UBYTE) (crc >> 8));
  135.       zsendline (v, (UBYTE) crc);
  136.     }
  137. }                /* End of void zsbhdr() */
  138.  
  139. /**********************************************************
  140.  *      void zshhdr(struct Vars *v, USHORT type)
  141.  *
  142.  * Send ZMODEM HEX header hdr of type type
  143.  **********************************************************/
  144. void 
  145. zshhdr (struct Vars *v, USHORT type)
  146. {
  147.   UBYTE *hdr = v->Txhdr;
  148.   short n;
  149.   USHORT crc;
  150.  
  151. #ifdef DEBUGLOG
  152.   xprsprintf (v->Msgbuf, "zshhdr: %s %lx\n", frametypes[type + FTOFFSET],
  153.           v->Rxbytes);
  154.   dlog (v, v->Msgbuf);
  155.   D (DEBUGINFO);
  156. #endif
  157.   sendline (v, ZPAD);
  158.   sendline (v, ZPAD);
  159.   sendline (v, ZDLE);
  160.   sendline (v, ZHEX);
  161.   zputhex (v, (UBYTE) type);
  162.   v->Crc32t = 0;
  163.  
  164.   crc = updcrc (type, 0);
  165.   for (n = 4; --n >= 0;)
  166.     {
  167.       zputhex (v, *hdr);
  168.       crc = updcrc (((USHORT) (*hdr++)), crc);
  169.     }
  170.  
  171.   crc = updcrc (((USHORT) 0), crc);
  172.   crc = updcrc (((USHORT) 0), crc);
  173.   zputhex (v, (UBYTE) (crc >> 8));
  174.   zputhex (v, (UBYTE) crc);
  175.  
  176.   /* Make it printable on remote machine */
  177.   sendline (v, '\r');
  178.   sendline (v, '\n');
  179.   /* Uncork the remote in case a fake XOFF has stopped data flow */
  180.   if (type != ZFIN)
  181.     sendline (v, XON);
  182. }                /* End of void zshhdr() */
  183.  
  184. /**********************************************************
  185.  *      void zsdata() and void zsda32()
  186.  *
  187.  * Send binary array buf of length length, with ending
  188.  * ZDLE sequence frameend
  189.  **********************************************************/
  190. void 
  191. zsdata (struct Vars *v, short length, USHORT frameend)
  192. {
  193.   UBYTE *buf, *outptr, c;
  194.   USHORT crc;
  195.   ULONG crc32;
  196.  
  197. #ifdef DEBUGLOG
  198.   xprsprintf (v->Msgbuf, v->Crc32t ? "zsda32: length=%ld end=%lx\n"
  199.       : "zsdata: length=%ld end=%lx\n", (long) length, (long) frameend);
  200.   dlog (v, v->Msgbuf);
  201.   D (DEBUGINFO);
  202. #endif
  203.  
  204.   buf = v->Pktbuf;
  205.   outptr = v->Outbuf + v->Outbuflen;
  206.   crc32 = 0xFFFFFFFFL;        /* zsda32() */
  207.   crc = 0;
  208.  
  209.   while (--length >= 0)
  210.     {
  211.       switch (DLE_actions[c = *buf])
  212.     {
  213.     case 2:
  214.       if (v->Lastzsent != '@')
  215.         goto sendit;
  216.       /* Fallthrough */
  217.     case 1:
  218.       *outptr++ = ZDLE;
  219.       c ^= 0x40;
  220.     sendit:
  221.     case 0:
  222.       *outptr++ = v->Lastzsent = c;
  223.     }
  224.       if (v->Crc32t)        /* zsda32() */
  225.     crc32 = UPDC32 ((0xFF & *buf++), crc32);
  226.       else
  227.     crc = updcrc (((USHORT) (*buf++)), crc);
  228.     }
  229.   *outptr++ = ZDLE;
  230.   *outptr++ = frameend;
  231.   v->Outbuflen = outptr - v->Outbuf;
  232.  
  233.   if (v->Crc32t)        /* zsda32() */
  234.     {
  235.       crc32 = UPDC32 (frameend, crc32);
  236.       crc32 = ~crc32;
  237.       for (length = 4; --length >= 0;)
  238.     {
  239.       zsendline (v, (int) crc32);
  240.       crc32 >>= 8;
  241.     }
  242.     }
  243.   else
  244.     {
  245.       crc = updcrc (frameend, crc);
  246.       crc = updcrc (((USHORT) 0), crc);
  247.       crc = updcrc (((USHORT) 0), crc);
  248.       zsendline (v, (UBYTE) (crc >> 8));
  249.       zsendline (v, (UBYTE) crc);
  250.     }
  251.  
  252.   if (frameend == ZCRCW)
  253.     xsendline (v, XON);
  254. }                /* End of void zsdata() */
  255.  
  256. /**********************************************************
  257.  *      short zrdata(struct Vars *v, UBYTE *buf, short length)
  258.  *
  259.  * Receive array buf of max length with ending ZDLE sequence
  260.  * and CRC-16.  Returns the ending character or error code.
  261.  **********************************************************/
  262. short
  263. zrdata (struct Vars *v, UBYTE * buf, short length)
  264. {
  265.   short c, d;
  266.   USHORT crc;
  267.  
  268. #ifdef DEBUGLOG
  269.   D (DEBUGINFO);
  270. #endif
  271.  
  272.   if (v->Rxframeind == ZBIN32)
  273.     return zrdat32 (v, buf, length);
  274.  
  275.   crc = v->Rxcount = 0;
  276.   for (;;)
  277.     {
  278.       if ((c = zdlread (v)) & ~0xFF)
  279.     {
  280.     crcfoo:
  281.       switch (c)
  282.         {
  283.         case GOTCRCE:
  284.         case GOTCRCG:
  285.         case GOTCRCQ:
  286.         case GOTCRCW:
  287.           crc = updcrc (((d = c) & 0xFF), crc);
  288.           if ((c = zdlread (v)) & ~0xFF)
  289.         goto crcfoo;
  290.           crc = updcrc (c, crc);
  291.           if ((c = zdlread (v)) & ~0xFF)
  292.         goto crcfoo;
  293.           crc = updcrc (c, crc);
  294.           if (crc & 0xFFFF)
  295.         {
  296.           strcpy (v->Msgbuf, GetLocalString( &li, MSG_BAD_DATA_PACKET_CRC_16 ));
  297.           return ERROR;
  298.         }
  299. #ifdef DEBUGLOG
  300.           xprsprintf (v->Msgbuf, "zrdata: cnt = %ld ret = %lx\n",
  301.               (long) v->Rxcount, (long) d);
  302.           dlog (v, v->Msgbuf);
  303.           D (DEBUGINFO);
  304. #endif
  305.           return d;
  306.         case GOTCAN:
  307.           strcpy (v->Msgbuf, GetLocalString( &li, MSG_SENDER_CANCELED ));
  308.           return ZCAN;
  309.         case TIMEOUT:
  310.           strcpy (v->Msgbuf, GetLocalString( &li, MSG_DATA_PACKET_TIMEOUT ));
  311.           return c;
  312.         case RCDO:
  313.           return c;
  314.         default:
  315.           strcpy (v->Msgbuf, GetLocalString( &li, MSG_UNRECOG_DATA_PACKET ));
  316.           return c;
  317.         }
  318.     }
  319.       if (--length < 0)
  320.     {
  321.       strcpy (v->Msgbuf, GetLocalString( &li, MSG_DATA_PACKET_TOO_LONG ));
  322.       return ERROR;
  323.     }
  324.       ++v->Rxcount;
  325.       *buf++ = c;
  326.       crc = updcrc (c, crc);
  327.       continue;
  328.     }
  329. }                /* End of short zrdata() */
  330.  
  331. /**********************************************************
  332.  *      short zrdat32(struct Vars *v, UBYTE *buf, short length)
  333.  *
  334.  * Receive array buf of max length with ending ZDLE sequence
  335.  * and CRC-32.  Returns the ending character or error code.
  336.  **********************************************************/
  337. short
  338. zrdat32 (struct Vars *v, UBYTE * buf, short length)
  339. {
  340.   short c, d;
  341.   ULONG crc32;
  342.  
  343. #ifdef DEBUGLOG
  344.   D (DEBUGINFO);
  345. #endif
  346.  
  347.   crc32 = 0xFFFFFFFFL;
  348.   v->Rxcount = 0;
  349.  
  350.   for (;;)
  351.     {
  352.       if ((c = zdlread (v)) & ~0xFF)
  353.     {
  354.     crcfoo:
  355.       switch (c)
  356.         {
  357.         case GOTCRCE:
  358.         case GOTCRCG:
  359.         case GOTCRCQ:
  360.         case GOTCRCW:
  361.           d = c;
  362.           c &= 0xFF;
  363.           crc32 = UPDC32 (c, crc32);
  364.           if ((c = zdlread (v)) & ~0xFF)
  365.         goto crcfoo;
  366.           crc32 = UPDC32 (c, crc32);
  367.           if ((c = zdlread (v)) & ~0xFF)
  368.         goto crcfoo;
  369.           crc32 = UPDC32 (c, crc32);
  370.           if ((c = zdlread (v)) & ~0xFF)
  371.         goto crcfoo;
  372.           crc32 = UPDC32 (c, crc32);
  373.           if ((c = zdlread (v)) & ~0xFF)
  374.         goto crcfoo;
  375.           crc32 = UPDC32 (c, crc32);
  376.           if (crc32 != 0xDEBB20E3)
  377.         {
  378.           strcpy (v->Msgbuf, GetLocalString( &li, MSG_BAD_DATA_PACKET_CRC_32 ));
  379.           return ERROR;
  380.         }
  381. #ifdef DEBUGLOG
  382.           xprsprintf (v->Msgbuf, "zrdat32: cnt = %ld ret = %lx\n",
  383.               (long) v->Rxcount, (long) d);
  384.           dlog (v, v->Msgbuf);
  385.           D (DEBUGINFO);
  386. #endif
  387.           return d;
  388.         case GOTCAN:
  389.           strcpy (v->Msgbuf, GetLocalString( &li, MSG_SENDER_CANCELED ));
  390.           return ZCAN;
  391.         case TIMEOUT:
  392.           strcpy (v->Msgbuf, GetLocalString( &li, MSG_DATA_PACKET_TIMEOUT ));
  393.           return c;
  394.         case RCDO:
  395.           return c;
  396.         default:
  397.           strcpy (v->Msgbuf, GetLocalString( &li, MSG_UNRECOG_DATA_PACKET ));
  398.           return c;
  399.         }
  400.     }
  401.       if (--length < 0)
  402.     {
  403.       strcpy (v->Msgbuf, GetLocalString( &li, MSG_DATA_PACKET_TOO_LONG ));
  404.       return ERROR;
  405.     }
  406.       ++v->Rxcount;
  407.       *buf++ = c;
  408.       crc32 = UPDC32 (c, crc32);
  409.       continue;
  410.     }
  411. }                /* End of short zrdat32() */
  412.  
  413. /**********************************************************
  414.  *      short zgethdr(struct Vars *v)
  415.  *
  416.  * Read a ZMODEM header to hdr, either binary or hex.
  417.  *  On success return type of header.
  418.  *  Otherwise return negative on error.
  419.  **********************************************************/
  420. short
  421. zgethdr (struct Vars *v)
  422. {
  423.   short c, cancount;
  424.   long n;
  425. #ifdef DEBUGLOG
  426.   UBYTE msgbuf[128];
  427.  
  428.   D (DEBUGINFO);
  429. #endif
  430.  
  431.   n = v->Baud;            /* Max characters before start of frame */
  432.   cancount = 5;
  433. again:
  434.   v->Rxframeind = v->Rxtype = 0;
  435.   switch (c = noxrd7 (v))
  436.     {
  437.     case RCDO:
  438.     case TIMEOUT:
  439.       goto fifi;
  440.     case CAN:
  441.       if (--cancount <= 0)
  442.     {
  443.       c = ZCAN;
  444.       goto fifi;
  445.     }
  446.     default:
  447.     agn2:
  448.       if (--n <= 0)
  449.     {
  450.       strcpy (v->Msgbuf, GetLocalString( &li, MSG_HEADER_SEARCH_GARBAGE ));
  451.       return ERROR;
  452.     }
  453.       if (c != CAN)
  454.     cancount = 5;
  455.       goto again;
  456.     case ZPAD:            /* This is what we want. */
  457.       break;
  458.     }
  459.   cancount = 5;
  460. splat:
  461.   switch (c = noxrd7 (v))
  462.     {
  463.     case ZPAD:
  464.       goto splat;
  465.     case RCDO:
  466.     case TIMEOUT:
  467.       goto fifi;
  468.     default:
  469.       goto agn2;
  470.     case ZDLE:            /* This is what we want. */
  471.       break;
  472.     }
  473.  
  474.   switch (c = noxrd7 (v))
  475.     {
  476.     case RCDO:
  477.     case TIMEOUT:
  478.       goto fifi;
  479.     case ZBIN:
  480.       v->Rxframeind = ZBIN;
  481.       v->Crc32 = FALSE;
  482.       c = zrbhdr (v);
  483.       break;
  484.     case ZBIN32:
  485.       v->Crc32 = v->Rxframeind = ZBIN32;
  486.       c = zrbhdr32 (v);
  487.       break;
  488.     case ZHEX:
  489.       v->Rxframeind = ZHEX;
  490.       v->Crc32 = FALSE;
  491.       c = zrhhdr (v);
  492.       break;
  493.     case CAN:
  494.       if (--cancount <= 0)
  495.     {
  496.       c = ZCAN;
  497.       goto fifi;
  498.     }
  499.       goto agn2;
  500.     default:
  501.       goto agn2;
  502.     }
  503.   v->Rxpos = rclhdr (v);
  504. fifi:
  505.   switch (c)
  506.     {
  507.     case GOTCAN:
  508.       c = ZCAN;
  509.     case ZNAK:
  510.     case ZCAN:
  511.     case ERROR:
  512.     case TIMEOUT:
  513.     case RCDO:
  514.       xprsprintf (v->Msgbuf, "%s %s ", frametypes[c + FTOFFSET],
  515.           (c >= 0) ? GetLocalString( &li, MSG_HEADER) : GetLocalString( &li, MSG_ERROR ));
  516. #ifdef DEBUGLOG
  517.     default:
  518.       if (c >= -3 && c <= FRTYPES)
  519.     xprsprintf (msgbuf, "zgethdr: %s @ %ld\n", frametypes[c + FTOFFSET],
  520.             v->Rxpos);
  521.       else
  522.     xprsprintf (msgbuf, "zgethdr: Unknown type %ld @ %ld\n", (long) c,
  523.             v->Rxpos);
  524.       dlog (v, msgbuf);
  525. #endif
  526.     }
  527.   return c;
  528. }                /* End of short zgethdr() */
  529.  
  530. /**********************************************************
  531.  *      short zrbhdr(struct Vars *v)
  532.  *
  533.  * Receive a binary style header (type and position)
  534.  **********************************************************/
  535. short 
  536. zrbhdr (struct Vars *v)
  537. {
  538.   UBYTE *hdr = v->Rxhdr;
  539.   short c, n;
  540.   USHORT crc;
  541.  
  542. #ifdef DEBUGLOG
  543.   D (DEBUGINFO);
  544. #endif
  545.  
  546.   if ((c = zdlread (v)) & ~0xFF)
  547.     return c;
  548.   v->Rxtype = c;
  549.   crc = updcrc (c, 0);
  550.  
  551.   for (n = 4; --n >= 0;)
  552.     {
  553.       if ((c = zdlread (v)) & ~0xFF)
  554.     return c;
  555.       crc = updcrc (c, crc);
  556.       *hdr++ = c;
  557.     }
  558.   if ((c = zdlread (v)) & ~0xFF)
  559.     return c;
  560.   crc = updcrc (c, crc);
  561.   if ((c = zdlread (v)) & ~0xFF)
  562.     return c;
  563.   crc = updcrc (c, crc);
  564.   if (crc & 0xFFFF)
  565.     {
  566.       strcpy (v->Msgbuf, GetLocalString( &li, MSG_BAD_HEADER_CRC_16 ));
  567.       return ERROR;
  568.     }
  569.   return v->Rxtype;
  570. }                /* End of short zrbhdr() */
  571.  
  572. /**********************************************************
  573.  *      short zrbhdr32(struct Vars *v)
  574.  *
  575.  * Receive a binary style header (type and position) with
  576.  * 32 bit FCS
  577.  **********************************************************/
  578. short
  579. zrbhdr32 (struct Vars *v)
  580. {
  581.   UBYTE *hdr = v->Rxhdr;
  582.   short c, n;
  583.   ULONG crc32;
  584.  
  585. #ifdef DEBUGLOG
  586.   D (DEBUGINFO);
  587. #endif
  588.  
  589.   if ((c = zdlread (v)) & ~0xFF)
  590.     return c;
  591.   v->Rxtype = c;
  592.   crc32 = 0xFFFFFFFFL;
  593.   crc32 = UPDC32 (c, crc32);
  594. #ifdef DEBUGLOG
  595.   xprsprintf (v->Msgbuf, "zrbhdr32: c=%x  crc32=%1x\n", c, crc32);
  596.   dlog (v, v->Msgbuf);
  597.   D (DEBUGINFO);
  598. #endif
  599.  
  600.   for (n = 4; --n >= 0;)
  601.     {
  602.       if ((c = zdlread (v)) & ~0xFF)
  603.     return c;
  604.       crc32 = UPDC32 (c, crc32);
  605.       *hdr++ = c;
  606. #ifdef DEBUGLOG
  607.       xprsprintf (v->Msgbuf, "zrbhdr32: c=%x  crc32=%1x\n", c, crc32);
  608.       dlog (v, v->Msgbuf);
  609.       D (DEBUGINFO);
  610. #endif
  611.     }
  612.   for (n = 4; --n >= 0;)
  613.     {
  614.       if ((c = zdlread (v)) & ~0xFF)
  615.     return c;
  616.       crc32 = UPDC32 (c, crc32);
  617. #ifdef DEBUGLOG
  618.       xprsprintf (v->Msgbuf, "zrbhdr32: c=%x  crc32=%1x\n", c, crc32);
  619.       dlog (v, v->Msgbuf);
  620.       D (DEBUGINFO);
  621. #endif
  622.     }
  623.   if (crc32 != 0xDEBB20E3)
  624.     {
  625.       strcpy (v->Msgbuf, GetLocalString( &li, MSG_BAD_HEADER_CRC_32 ));
  626.       return ERROR;
  627.     }
  628.   return v->Rxtype;
  629. }                /* End of short zrbhdr32() */
  630.  
  631. /**********************************************************
  632.  *      short zrhhdr(struct Vars *v)
  633.  *
  634.  * Receive a hex style header (type and position)
  635.  **********************************************************/
  636. short
  637. zrhhdr (struct Vars *v)
  638. {
  639.   UBYTE *hdr = v->Rxhdr;
  640.   short c, n;
  641.   USHORT crc;
  642.  
  643. #ifdef DEBUGLOG
  644.   D (DEBUGINFO);
  645. #endif
  646.  
  647.   if ((c = zgethex (v)) < 0)
  648.     return c;
  649.   v->Rxtype = c;
  650.   crc = updcrc (c, 0);
  651.  
  652.   for (n = 4; --n >= 0;)
  653.     {
  654.       if ((c = zgethex (v)) < 0)
  655.     return c;
  656.       crc = updcrc (c, crc);
  657.       *hdr++ = c;
  658.     }
  659.   if ((c = zgethex (v)) < 0)
  660.     return c;
  661.   crc = updcrc (c, crc);
  662.   if ((c = zgethex (v)) < 0)
  663.     return c;
  664.   crc = updcrc (c, crc);
  665.   if (crc & 0xFFFF)
  666.     {
  667.       strcpy (v->Msgbuf, GetLocalString( &li, MSG_BAD_HEADER_CRC ));
  668.       return ERROR;
  669.     }
  670.   if (readock (v, 1) == '\r')
  671.     readock (v, 1);        /* Throw away possible cr/lf */
  672.   return v->Rxtype;
  673. }                /* End of short zrhhdr() */
  674.  
  675. /**********************************************************
  676.  *      void zputhex(struct Vars *v, UBYTE c)
  677.  *
  678.  * Send a byte as two hex digits
  679.  **********************************************************/
  680. void 
  681. zputhex (struct Vars *v, UBYTE c)
  682. {
  683.   static char digits[] = "0123456789abcdef";
  684.  
  685. #ifdef DEBUGLOG
  686.   D (DEBUGINFO);
  687. #endif
  688.  
  689.   sendline (v, digits[(c >> 4) & 0x0F]);
  690.   sendline (v, digits[c & 0x0F]);
  691. }                /* End of void zputhex() */
  692.  
  693. /**********************************************************
  694.  *      void zsendline(struct Vars *v, UBYTE c)
  695.  *
  696.  * Send character c with ZMODEM escape sequence encoding.
  697.  * Escape ZDLE, real DLE, XON, XOFF, and CR following @ (Telenet net escape)
  698.  **********************************************************/
  699. void 
  700. zsendline (struct Vars *v, UBYTE c)
  701. {
  702. #ifdef DEBUGLOG
  703.   D (DEBUGINFO);
  704. #endif
  705.  
  706.   switch (DLE_actions[c])
  707.     {
  708.     case 2:
  709.       if (v->Lastzsent != '@')
  710.     goto sendit;
  711.       /* Fallthrough */
  712.     case 1:
  713.       xsendline (v, ZDLE);
  714.       c ^= 0x40;
  715.     sendit:
  716.     case 0:
  717.       xsendline (v, v->Lastzsent = c);
  718.     }
  719. }                /* End of void zsendline() */
  720.  
  721. /**********************************************************
  722.  *      short zgethex(struct Vars *v)
  723.  *
  724.  * Decode two lower case hex digits into an 8 bit byte value
  725.  **********************************************************/
  726. short
  727. zgethex (struct Vars *v)
  728. {
  729.   short c, n;
  730.  
  731. #ifdef DEBUGLOG
  732.   D (DEBUGINFO);
  733. #endif
  734.  
  735.   if ((n = noxrd7 (v)) < 0)
  736.     return n;
  737.   n -= '0';
  738.   if (n > 9)
  739.     n -= ('a' - ':');
  740.   if (n & ~0xF)
  741.     return ERROR;
  742.  
  743.   if ((c = noxrd7 (v)) < 0)
  744.     return c;
  745.   c -= '0';
  746.   if (c > 9)
  747.     c -= ('a' - ':');
  748.   if (c & ~0xF)
  749.     return ERROR;
  750.  
  751.   return (short) (n << 4 | c);
  752. }                /* End of short zgethex() */
  753.  
  754. /**********************************************************
  755.  *      short zdlread(struct Vars *v)
  756.  *
  757.  * Read a byte, checking for ZMODEM escape encoding
  758.  * including CAN*5 which represents a quick abort.
  759.  **********************************************************/
  760. short 
  761. zdlread (struct Vars *v)
  762. {
  763.   short c;
  764.  
  765. #ifdef DEBUGLOG
  766.   D (DEBUGINFO);
  767. #endif
  768.  
  769.   if ((c = readock (v, v->Rxtimeout)) != ZDLE)
  770.     return c;
  771.   if ((c = readock (v, v->Rxtimeout)) < 0)
  772.     return c;
  773.   if (c == CAN && (c = readock (v, v->Rxtimeout)) < 0)
  774.     return c;
  775.   if (c == CAN && (c = readock (v, v->Rxtimeout)) < 0)
  776.     return c;
  777.   if (c == CAN && (c = readock (v, v->Rxtimeout)) < 0)
  778.     return c;
  779.   switch (c)
  780.     {
  781.     case CAN:
  782.       return GOTCAN;
  783.     case ZCRCE:
  784.     case ZCRCG:
  785.     case ZCRCQ:
  786.     case ZCRCW:
  787.       return (short) (c | GOTOR);
  788.     case ZRUB0:
  789.       return 0x7F;
  790.     case ZRUB1:
  791.       return 0xFF;
  792.     default:
  793.       if ((c & 0x60) == 0x40)
  794.     return (short) (c ^ 0x40);
  795.       break;
  796.     }
  797.   strcpy (v->Msgbuf, GetLocalString( &li, MSG_BAD_ZMODEM_ESC_SEQ ));
  798.   return ERROR;
  799. }                /* End of short zdlread() */
  800.  
  801. /**********************************************************
  802.  *      short noxrd7(struct Vars *v)
  803.  *
  804.  * Read a character from the modem line with timeout.
  805.  * Eat parity, XON and XOFF characters.
  806.  **********************************************************/
  807. short 
  808. noxrd7 (struct Vars *v)
  809. {
  810.   short c;
  811.  
  812. #ifdef DEBUGLOG
  813.   D (DEBUGINFO);
  814. #endif
  815.  
  816.   for (;;)
  817.     {
  818.       if ((c = readock (v, v->Rxtimeout)) < 0)
  819.     return c;
  820.       switch (c &= 0x7F)
  821.     {
  822.     case XON:
  823.     case XOFF:
  824.       continue;
  825.     default:
  826.       return c;
  827.     }
  828.     }
  829. }                /* short noxrd7() */
  830.  
  831. /**********************************************************
  832.  *      void stohdr(struct Vars *v, long pos)
  833.  *
  834.  * Store long integer pos in Txhdr
  835.  **********************************************************/
  836. void 
  837. stohdr (struct Vars *v, long pos)
  838. {
  839. #ifdef DEBUGLOG
  840.   D (DEBUGINFO);
  841. #endif
  842.  
  843.   v->Txhdr[ZP0] = pos;
  844.   pos >>= 8;
  845.   v->Txhdr[ZP1] = pos;
  846.   pos >>= 8;
  847.   v->Txhdr[ZP2] = pos;
  848.   pos >>= 8;
  849.   v->Txhdr[ZP3] = pos;
  850. }                /* End of void stohdr() */
  851.  
  852. /**********************************************************
  853.  *      long rclhdr(struct Vars *v)
  854.  *
  855.  * Recover a long integer from a header
  856.  **********************************************************/
  857. long 
  858. rclhdr (struct Vars *v)
  859. {
  860.   long l;
  861.  
  862. #ifdef DEBUGLOG
  863.   D (DEBUGINFO);
  864. #endif
  865.  
  866.   l = v->Rxhdr[ZP3];
  867.   l = (l << 8) | v->Rxhdr[ZP2];
  868.   l = (l << 8) | v->Rxhdr[ZP1];
  869.   l = (l << 8) | v->Rxhdr[ZP0];
  870.   return l;
  871. }                /* End of long rclhdr() */
  872. /* End of Zm.c source */
  873.